Über ArchUnit
Eine Herausforderung in Software-Projekten besteht oft darin, spezifische Architekturregeln sicherzustellen. Textuelle Formen der Dokumentation und Diagramme sind im Arbeitsalltag wenig präsent, und so schleichen sich im Laufe des Projektlebenszyklus häufig Verletzungen dieser festgelegten Regeln ein.
ArchUnit ist eine relativ junge Bibliothek, die es Entwicklern erlaubt, Architekturregeln in Form ausführbarer Tests zu definieren und mit gängigen Werkzeugen und Test-Frameworks wie Gradle, Maven, JUnit, Surefire & Co. auszuführen. Diese Form der lebendigen Dokumentation erleichtert es, die Konsistenz der Regeln zu erhalten und Abweichungen davon zumindest bewusst in Kauf zu nehmen, statt später zufällig darauf zu stoßen.
Im folgenden Kurzbeispiel wollen wir einen Architekturtest mit ArchUnit erstellen; als Build-Werkzeug kommt Gradle zur Anwendung.
Integration
Um ArchUnit nutzen zu können, müssen wir unserer Konfigurationsdatei build.gradle
lediglich eine Abhängigkeit hinzufügen:
testCompile 'com.tngtech.archunit:archunit-junit:0.4.0'
Architekturtests schreiben
Wir nehmen eine Architektur an, in der wir zwei Packages names net.seibertmedia.a
und net.seibertmedia.b
haben. Nun wollen wir verhindern, dass Klassen aus dem Sub-Package a
auf das Sub-Package b
zugreifen.
Dank der Fluent-API ist der Einstieg schnell bewerkstelligt und eine Lösung sieht wie folgt aus:
package architecture; import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; import com.tngtech.archunit.core.domain.JavaClasses; import com.tngtech.archunit.core.importer.ClassFileImporter; import com.tngtech.archunit.lang.ArchRule; import org.junit.Before; import org.junit.Test; public class ArchitecturalConstraintsTest { private final ClassFileImporter importer = new ClassFileImporter(); private JavaClasses classesAnalyzed; @Before public void importClasses() { classesAnalyzed = importer.importPackages("net.seibertmedia"); } @Test public void classesFromPackageAMustNotAccessClassesInPackageB() throws Exception { ArchRule rule = noClasses().that().resideInAPackage("net.seibertmedia.a..") .should().accessClassesThat().resideInAPackage("net.seibertmedia.b.."); rule.check(classesAnalyzed); } }
Wenn wir mittels gradle test
nun die Tests ausführen, bekommen wir - sofern beispielsweise ein solcher Zugriff erfolgt ist - eine entsprechende Fehlermeldung:
% gradle test --info 1 [..] Gradle Test Executor 1 started executing tests. architecture.ArchitecturalConstraintsTest > classesFromPackageAMustNotAccessClassesInPackageB STANDARD_ERROR Gradle Test Executor 1 finished executing tests. architecture.ArchitecturalConstraintsTest > classesFromPackageAMustNotAccessClassesInPackageB FAILED java.lang.AssertionError: Architecture Violation [Priority: MEDIUM] - Rule 'no classes that reside in a package 'net.seibertmedia.a..' should access classes that reside in a package 'net.seibertmedia.b..'' was violated: Method <net.seibertmedia.a.ClassInPackageA.<init>()> calls constructor <net.seibertmedia.b.ClassInPackageB.<init>()> in (ClassInPackageA.java:7) at com.tngtech.archunit.lang.ArchRule$Assertions.assertNoViolation(ArchRule.java:81) at com.tngtech.archunit.lang.ArchRule$Factory$SimpleArchRule.check(ArchRule.java:153) at com.tngtech.archunit.lang.syntax.ObjectsShouldInternal.check(ObjectsShouldInternal.java:75) at com.tngtech.archunit.lang.syntax.ClassesShouldThatInternal.check(ClassesShouldThatInternal.java:294) at architecture.ArchitecturalConstraintsTest.classesFromPackageAMustNotAccessClassesInPackageB(ArchitecturalConstraintsTest.java:27) 1 test completed, 1 failed Finished generating test XML results (0.011 secs) into: /data/project/smedia-archunit-beispiele/build/test-results Generating HTML test report... Finished generating test html results (0.017 secs) into: /data/project/smedia-archunit-beispiele/build/reports/tests
Ausführlichere Informationen zur ArchUnit-Syntax, zur Konfiguration und zu weiteren konkreten Beispielen finden sich in der Projekt-Dokumentation auf GitHub und diesem weiterführenden Blog-Artikel.
Ihr Partner für individuelle Software-Projekte
Planen Sie bereits ein konkretes Software-Projekt? Oder gibt es bestimmte Prozesse in Ihrem Unternehmen, die Ihnen schon lange Kopfzerbrechen bereiten? Bremst ein System oder eine Schnittstelle Ihre Mitarbeiter auf der einen oder Ihre Kunden auf der anderen Seite aus? Dann sprechen Sie mit uns darüber! Wir freuen uns darauf, gemeinsam eine individuelle Lösung zu entwickeln – bei höchster Qualität und voller Kostenkontrolle.
Weiterführende Infos
Was agile Software-Projekte dem Kunden bringen
Vorgehen nach Scrum: Die beste Wahl für den Kunden, die Agentur – und das Produkt
Echte Integration: Das Zusammenspiel von JIRA, Stash und Bamboo im Entwicklungsprozess
Der Beginn eines Happy Ends: Initialer Anforderungs-Workshop für erfolgreiche Projekte
Darum ist eine regelmäßige Kundenpräsenz beim Entwicklungsteam so sinnvoll
Mehr über die Creative-Commons-Lizenz erfahren